package com.hopes.bizz.risk.statistic.serivce.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.bizz.risk.common.constant.GisRequestEnums;
import com.hopes.bizz.risk.common.constant.enums.RiskSysDictEnum;
import com.hopes.bizz.risk.control.service.RiskObjectService;
import com.hopes.bizz.risk.control.service.RiskUnitEventService;
import com.hopes.bizz.risk.hid.service.RiskHidHiddenDangerService;
import com.hopes.bizz.risk.parkgis.vo.*;
import com.hopes.bizz.risk.statistic.serivce.ParkGisService;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 园区双重预防一张图
 * @time 2023/11/13 9:45
 */
@RequiredArgsConstructor
@Service("parkGisService")
public class ParkGisServiceImpl implements ParkGisService {

    private final RiskObjectService riskObjectService;
    private final RiskUnitEventService riskUnitEventService;
    private final RiskHidHiddenDangerService riskHidHiddenDangerService;

    @Override
    @SuppressWarnings("rawtypes")
    public List<BasicInfoVO> basicInfo() {
        final List<BasicInfoVO> basicInfoVOList = new ArrayList<>();
        // 1、所有企业数据
        final List<SysDictItem> companyList = DictResolver.getItemsByType(AdminDictEnum.sys_company);
        // 2、查询风险分析对象
        final Map<Long, Long> riskObjectMap = riskObjectService.countGroupByCompany();
        final Map<Long, Long> riskUnitEventMap = riskUnitEventService.countGroupByCompany();
        final Map<Long, Long> riskHidHiddenDangerMap = riskHidHiddenDangerService.countGroupByCompany();

        for (SysDictItem dictItem : companyList) {
            final long orgId = Long.parseLong(dictItem.getCode());
            final Map objectMap = MapUtil.get(riskObjectMap, orgId, Map.class);
            final Map unitEventMap = MapUtil.get(riskUnitEventMap, orgId, Map.class);
            final Map hiddenDangerMap = MapUtil.get(riskHidHiddenDangerMap, orgId, Map.class);

            final BasicInfoVO basicInfoVO = new BasicInfoVO();
            basicInfoVO.setOrgId(orgId);
            basicInfoVO.setObjectNum(MapUtil.getInt(objectMap, "count", 0));
            basicInfoVO.setEventNum(MapUtil.getInt(unitEventMap, "count", 0));
            basicInfoVO.setHiddenNum(MapUtil.getInt(hiddenDangerMap, "count", 0));

            basicInfoVOList.add(basicInfoVO);
        }
        return basicInfoVOList;
    }

    @Override
    public List<RiskLevelVO> riskObjectLevel() {
        // 1、结果集
        final List<RiskLevelVO> listRes = new ArrayList<>();
        final List<SysDictItem> orgList = DictResolver.getItemsByType(AdminDictEnum.sys_company);
        final List<SysDictItem> riskLevelList = DictResolver.getItemsByType(RiskSysDictEnum.risk_level);
        // 2、根据企业、风险等级统计
        final List<OrgLevelVO> orgLevelVOList = riskObjectService.listGroupLevelCompany();
        // 3、根据企业分类
        final Map<Long, List<OrgLevelVO>> listMap= orgLevelVOList.stream().filter(e -> ObjUtil.isNull(e.getOrgId())).collect(Collectors.groupingBy(OrgLevelVO::getOrgId));
        for (SysDictItem orgItem : orgList) {
            final long orgId = Long.parseLong(orgItem.getCode());
            final RiskLevelVO item = new RiskLevelVO();
            item.setOrgId(orgId);
            item.setRiskLevelList(buildRiskLevelList(riskLevelList, listMap.get(orgId)));
            listRes.add(item);
        }
        return listRes;
    }

    @Override
    public List<RiskLevelVO> riskUnitEventLevel() {
        // 1、结果集
        final List<RiskLevelVO> listRes = new ArrayList<>();
        final List<SysDictItem> orgList = DictResolver.getItemsByType(AdminDictEnum.sys_company);
        final List<SysDictItem> riskLevelList = DictResolver.getItemsByType(RiskSysDictEnum.risk_level);
        // 2、根据企业、风险等级统计
        final List<OrgLevelVO> orgLevelVOList = riskUnitEventService.listGroupLevelCompany();
        // 3、根据企业分类
        final Map<Long, List<OrgLevelVO>> listMap= orgLevelVOList.stream().filter(e -> ObjUtil.isNull(e.getOrgId())).collect(Collectors.groupingBy(OrgLevelVO::getOrgId));
        for (SysDictItem orgItem : orgList) {
            final long orgId = Long.parseLong(orgItem.getCode());
            final RiskLevelVO item = new RiskLevelVO();
            item.setOrgId(orgId);
            item.setRiskLevelList(buildRiskLevelList(riskLevelList, listMap.get(orgId)));
            listRes.add(item);
        }
        return listRes;
    }

    @Override
    public List<HidLevelVO> riskHiddenLevel(GisRequestEnums.GisCalEnum gisCalEnum) {
        final List<HidLevelVO> hidLevelList = new ArrayList<>();
        if (ObjUtil.isNull(gisCalEnum)) {
            return hidLevelList;
        }
        final Calendar instance = Calendar.getInstance();
        final Date startTime = computeStartTime(instance, gisCalEnum);

        final List<SysDictItem> orgList = DictResolver.getItemsByType(AdminDictEnum.sys_company);
        final List<SysDictItem> dangerTypeList = DictResolver.getItemsByType(RiskSysDictEnum.danger_type);

        final List<OrgHidVO> orgHidVOList = riskHidHiddenDangerService.listGroupLevelCompany(startTime);
        final Map<Long, List<OrgHidVO>> listMap = orgHidVOList.stream().filter(e -> ObjUtil.isNotNull(e.getOrgId())).collect(Collectors.groupingBy(OrgHidVO::getOrgId));

        for (SysDictItem dictItem : orgList) {
            final long orgId = Long.parseLong(dictItem.getCode());

            final HidLevelVO hidLevelVO = new HidLevelVO();
            hidLevelVO.setOrgId(orgId);
            hidLevelVO.setHidLevelList(buildHidLevelList(dangerTypeList, listMap.get(orgId)));
            hidLevelList.add(hidLevelVO);
        }
        return hidLevelList;
    }

    private List<OrgHidVO> buildHidLevelList(List<SysDictItem> dangerTypeList, List<OrgHidVO> orgHidVOList) {
        final List<OrgHidVO> resList = dangerTypeList.stream().map(e -> {
            final OrgHidVO orgHidVO = new OrgHidVO();
            orgHidVO.setCount(0);
            orgHidVO.setHidLevel(Integer.valueOf(e.getCode()));
            return orgHidVO;
        }).collect(Collectors.toList());

        for (OrgHidVO orgHidVO : resList) {
            final Integer count = orgHidVOList.stream().filter(e ->
                    ObjUtil.isNotNull(e.getHidLevel()) && e.getHidLevel().equals(orgHidVO.getHidLevel())).findFirst().map(OrgHidVO::getCount).orElse(0);
            orgHidVO.setCount(count);
        }
        return resList;
    }

    private Date computeStartTime(Calendar instance, GisRequestEnums.GisCalEnum gisCalEnum) {
        if (gisCalEnum.equals(GisRequestEnums.GisCalEnum.DAY)) {
            return DateUtils.dateLimitDay(instance.getTime());
        } else if (gisCalEnum.equals(GisRequestEnums.GisCalEnum.MONTH)) {
            return DateUtils.dateLimitMonth(instance.getTime());
        } else if (gisCalEnum.equals(GisRequestEnums.GisCalEnum.YEAR)){
            return DateUtils.parseDate(String.valueOf(instance.get(Calendar.YEAR)), DateUtils.FORMAT_YEAR);
        }
        return null;
    }

    private List<OrgLevelVO> buildRiskLevelList(List<SysDictItem> riskLevelList, List<OrgLevelVO> levelVOList) {
        if (CollUtil.isEmpty(levelVOList)) {
            return riskLevelList.stream().map(e -> {
                final OrgLevelVO orgLevelVO = new OrgLevelVO();
                orgLevelVO.setRiskLevel(Integer.valueOf(e.getCode()));
                orgLevelVO.setCount(0);
                return orgLevelVO;
            }).collect(Collectors.toList());
        }

        final Map<Integer, Integer> countMap = levelVOList.stream().filter(e -> ObjUtil.isNotNull(e.getRiskLevel())).collect(Collectors.toMap(OrgLevelVO::getRiskLevel, OrgLevelVO::getCount));
        return riskLevelList.stream().map(e -> {
            final OrgLevelVO orgLevelVO = new OrgLevelVO();
            orgLevelVO.setRiskLevel(Integer.valueOf(e.getCode()));
            orgLevelVO.setCount(MapUtil.getInt(countMap, Integer.valueOf(e.getCode()), 0));
            return orgLevelVO;
        }).collect(Collectors.toList());
    }




}
